home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume7 / aaakeys < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  21.3 KB

  1. Subject:  v07i035:  Ann Arbor XL key uploader
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: Rayan Zachariassen <seismo!utai!rayan>
  6. Mod.sources: Volume 7, Issue 35
  7. Archive-name: aaaxlkeys
  8.  
  9.  
  10. [  If you are fortunate enough to have both an XL and USG Unix, note
  11.    that this program uses index/rindex, not strchr/strrchr.  -r$ ]
  12.  
  13. #!/bin/sh
  14. # This is a shell archive.  Remove anything before this line,
  15. # then unpack it by saving it in a file and typing "sh file".
  16. # If all goes well, you will see the message "No problems found."
  17.  
  18. # Exit status; set to 1 on "wc" errors or if would overwrite.
  19. STATUS=0
  20. # Contents:  README Makefile aaxl.c aaxl.l
  21.  
  22. echo x - README
  23. if test -f README ; then
  24.     echo README exists, putting output in $$README
  25.     OUT=$$README
  26.     STATUS=1
  27. else
  28.     OUT=README
  29. fi
  30. sed 's/^X//' > $OUT <<'@//E*O*F README//'
  31. X        Ann Arbor XL series programmable strings uploader
  32.  
  33. XI wrote this one evening partly for relaxation, partly as a tangible example
  34. Xof my coding style. I was having a friendly discussion with one of our local
  35. Xpurists (hi Geoff!) about how code should look like, which tradeoffs to make,
  36. Xetc. Some of his comments on the first draft of this were adopted in the code,
  37. Xbecause they seemed quite sensible within my philosophy as well. I am not a
  38. Xgreat fan of remapping keyboards (though it is useful at times) and don't use
  39. Xthis program regularly, though another fellow around here does. I'm sending it
  40. Xout primarily as a sample of good (I think) coding, in case anyone cares for
  41. Xa non-trivial example. Besides, some people might find it useful. No claims
  42. Xare made about the portability of this stuff. It works on 4.n on Vaxen.
  43. XThere is one large compiler dependency, clearly marked. I'll take elegant over
  44. Xproper most any day...
  45.  
  46. Xrayan
  47.  
  48. XRayan Zachariassen <rayan@utai.uucp>
  49. XAI group, University of Toronto
  50.  
  51. @//E*O*F README//
  52. chmod u=rw,g=rw,o=rw $OUT
  53.  
  54. echo x - Makefile
  55. if test -f Makefile ; then
  56.     echo Makefile exists, putting output in $$Makefile
  57.     OUT=$$Makefile
  58.     STATUS=1
  59. else
  60.     OUT=Makefile
  61. fi
  62. sed 's/^X//' > $OUT <<'@//E*O*F Makefile//'
  63. X##  Quick Makefile for Ann Arbor XL program
  64.  
  65. XCFLAGS=-O
  66. Xaaxl:    aaxl.c
  67. X    $(CC) $(CFLAGS) aaxl.c -o aaxl
  68.  
  69. Xinstall:
  70. X    @echo cp aaxl and aaxl.l to appropriate places
  71. X    cp aaxl /usr/bin
  72. X    strip /usr/bin/aaxl
  73. X    cp aaxl.l /usr/man/man1/aaxl.1
  74. @//E*O*F Makefile//
  75. chmod u=rw,g=rw,o=rw $OUT
  76.  
  77. echo x - aaxl.c
  78. if test -f aaxl.c ; then
  79.     echo aaxl.c exists, putting output in $$aaxl.c
  80.     OUT=$$aaxl.c
  81.     STATUS=1
  82. else
  83.     OUT=aaxl.c
  84. fi
  85. sed 's/^X//' > $OUT <<'@//E*O*F aaxl.c//'
  86. X/*
  87. X * Ann Arbor XL series programmable strings uploader.
  88. X */
  89.  
  90. X#ifndef lint
  91. Xstatic char *RCSid = "$Header: aaxl.c,v 1.1 86/05/09 19:48:10 rayan Exp $";
  92. X#endif
  93.  
  94. X/*
  95. X * Copyright (c) 1986 by Rayan S. Zachariassen.
  96. X *
  97. X * Permission is granted to anyone to use this software for any
  98. X * purpose on any computer system, and to redistribute it, subject
  99. X * to the following four restrictions:
  100. X *
  101. X * 1. The author is not responsible for the consequences of use of
  102. X *    this software, no matter how awful, even if they arise
  103. X *    from imperfections in it.
  104. X *
  105. X * 2. The origin of this software must not be misrepresented, either
  106. X *    by explicit claim or by omission.
  107. X *
  108. X * 3. Altered versions must be plainly marked as such, and must not
  109. X *    be misrepresented as being the original software, but must be
  110. X *    marked as being an alteration of this software.
  111. X *
  112. X * 4. Commercial or any for-profit redistribution of this software is
  113. X *    prohibited unless by prior written agreement from the author.
  114. X */
  115.  
  116.  
  117. X/*
  118. X * Several files may be given as arguments. With no files specified,
  119. X * $HOME/.aaxlrc is read. A filename of - reads from stdin.
  120. X * The options are:
  121. X *
  122. X *    -a    append, i.e. don't clear to default programmable strings.
  123. X *    -d    debug, prints out memory usage stats instead of uploading.
  124. X *    -v    verbose, print out body of upload string to stdout.
  125. X *    -l    lock, to lock programmable strings until power-up or SETUP-Z
  126. X *
  127. X * To initialize the programmable strings on your XL, use
  128. X *
  129. X *    aaxl /dev/null
  130. X *
  131. X * Format of files:
  132. X *
  133. X * Each input file contains lines specifying a key to upload a programmable
  134. X * string for. Lines starting with #, and empty lines, are ignored.
  135. X * The format of each line is
  136. X *
  137. X *     name <whitespace> options [ <whitespace> <tab> text ]
  138. X *
  139. X * where <whitespace> is blanks, tabs, and commas. The text is optional,
  140. X * if not there the key will revert to default programmed text (usually none).
  141. X * This can be used to change other behavior of a key.
  142. X *
  143. X * The options field consists of keywords from the following lists:
  144. X *
  145. X *    ctrl, shift, ctrl-shift, meta, 0-31, 64    - shift level
  146. X *    host, display, graphics            - transmit direction
  147. X *    never, always                - repeat attribute
  148. X *    level                    - this is a shift key
  149. X *    normal                    - everything normal
  150. X *
  151. X * The defaults for all but the 'normal' keyword are whatever the previous
  152. X * option value was for the previous key. The normal (and initial default)
  153. X * values correspond to all-zero parameters. See the XL manual for detailed
  154. X * explanation of the options.
  155. X *
  156. X * The text field follows one or more blanks or tabs after the option field
  157. X * and consists of everything from there till a newline. The string may contain
  158. X * all the usual C string escapes (\###, \n\t\s\a\b\f\r\e), and in addition
  159. X * may contain one sequence like \`...` where ... is a command to be executed
  160. X * by the shell. The result (stdout) of the command is interpolated in place
  161. X * of the \` escape.
  162. X *
  163. X * This program reports errors, including XL memory overflow that could
  164. X * occur. All errors are fatal. The program doesn't send an upload string
  165. X * to the terminal unless no errors were detected at all. Memory allocation
  166. X * for the upload string is done dynamically in the program, so excessively
  167. X * large string sequences are handled. Space-optimal output is produced.
  168. X *
  169. X * Rayan Zachariassen
  170. X * rayan@utai.uucp
  171. X *
  172. X * Toronto, March 27 1986
  173. X *
  174. X */
  175.  
  176. X#include <stdio.h>
  177. X#include <ctype.h>
  178.  
  179. X#define USAGE    "aaxl [-a] [-d] [-l] [-v] [file ...]"
  180.  
  181. X#define    RCFILE        ".aaxlrc"    /* file to read from in $HOME */
  182. X#define    MEMSIZ        896        /* memory size in bytes of an XL */
  183. X#define    MAXPOWERMEM    255        /* non-volatile power-on memory size */
  184.  
  185. X#define    CLICK        1024        /* memory increased in chunks of this */
  186. X#define    PREAMBLE    "\033P>"
  187. X#define    POSTAMBLE    "\033\\"
  188. X#define    MAXONEUSE    (2*MEMSIZ+3+2+1+1+1+4+2+(sizeof POSTAMBLE)-1)
  189.  
  190. Xint    lineno, memusage;
  191. Xchar    *program, *file, *out;
  192.  
  193. Xextern char    *index(), *rindex(), *itoa(), *malloc(), *realloc();
  194. Xextern FILE    *popen();
  195.  
  196. Xextern int    errno;
  197. Xextern char    *sys_errlist[];
  198.  
  199. Xextern int    getopt();
  200. Xextern char    *optarg;
  201. Xextern int    optind;
  202.  
  203. Xmain(argc, argv)
  204. Xint    argc;
  205. Xchar    *argv[];
  206. X{
  207. X    int        ch, errflg, keysappend, debug, lock, verbose;
  208. X    unsigned int    xlsize;
  209. X    char        *xlmem, buf[BUFSIZ];
  210. X    FILE        *fp;
  211.  
  212. X    program = argv[0];
  213. X    if (out = rindex(program, '/'))
  214. X        program = out + 1;
  215.  
  216. X    errflg = keysappend = debug = lock = verbose = 0;
  217. X    while ((ch = getopt(argc, argv, "adlv")) != EOF) {
  218. X        switch ((char) ch) {
  219. X        case 'a':
  220. X            keysappend = 1;
  221. X            break;
  222. X        case 'd':
  223. X            debug = 1;
  224. X            break;
  225. X        case 'l':
  226. X            lock = 1;
  227. X            break;
  228. X        case 'v':
  229. X            verbose = 1;
  230. X            break;
  231. X        default:
  232. X            errflg++;
  233. X            break;
  234. X        }
  235. X    }
  236. X    if (errflg) {
  237. X        fprintf(stderr, "Usage: %s\n", USAGE);
  238. X        exit(errflg);
  239. X    }
  240. X    if (optind == argc) {
  241. X        char        *cp;
  242. X        extern char    *getenv();
  243.  
  244. X        cp = getenv("HOME");
  245. X        if (*cp && chdir(cp) < 0) {
  246. X            fprintf(stderr, "%s: chdir(%s): %s\n", program,
  247. X                    cp, sys_errlist[errno]);
  248. X            exit(1);
  249. X        } else if (cp == 0) {
  250. X            fprintf(stderr,
  251. X                "%s: no $HOME environment variable\n", program);
  252. X            exit(1);
  253. X        }
  254. X        argv[--optind] = RCFILE;
  255. X    }
  256. X    xlsize = CLICK + MAXONEUSE;
  257. X    if ((xlmem = malloc(xlsize)) == 0) {
  258. X        fprintf(stderr, "%s: malloc failure\n", program);
  259. X        exit(1);
  260. X    }
  261. X    out = xlmem;
  262. X    append(PREAMBLE);
  263. X    /*
  264. X     *    keysappend    lock        global parameter
  265. X     *
  266. X     *        0    0        0 or 1
  267. X     *        0    1        3
  268. X     *        1    0        empty
  269. X     *        1    1        2
  270. X     */
  271. X    if (!keysappend)
  272. X        append(itoa(3*lock));
  273. X    else if (lock)
  274. X        append("2");
  275. X    for (; optind < argc; optind++) {
  276. X        file = argv[optind];
  277. X        if (strcmp(file, "-") == 0 && (fp = fdopen(0, "r")) == NULL) {
  278. X            perror("stdin");
  279. X            exit(1);
  280. X        } else if ((fp = fopen(file, "r")) == NULL) {
  281. X            perror(file);
  282. X            exit(1);
  283. X        }
  284. X        lineno = 0;
  285. X        memusage = 0;
  286. X        while (fgets(buf, sizeof buf, fp)) {
  287. X            lineno++;
  288. X            buf[strlen(buf)-1] = '\0';
  289. X            if (buf[0] == '#' || buf[0] == '\0')
  290. X                continue;
  291. X            doline(buf);
  292. X            if (out - xlmem >= xlsize - MAXONEUSE) {
  293. X                char    *cp;
  294.  
  295. X                if ((cp = realloc(xlmem, xlsize + CLICK)) == 0)
  296. X                    error("realloc failure\n", (char *)0);
  297. X                out = cp + (xlmem - out);
  298. X                xlmem = cp;
  299. X                xlsize += CLICK;
  300. X            }
  301. X        }
  302. X        (void) fclose(fp);
  303. X        *out = 0;
  304. X    }
  305. X    if (verbose)
  306. X        printf("%s\n", xlmem + sizeof PREAMBLE - 1);
  307. X    if (memusage > MEMSIZ) {
  308. X        fprintf(stderr,
  309. X            "%s: Ann Arbor XL memory not large enough!\n", program);
  310. X        debug = 1;
  311. X        errflg = 1;
  312. X    }
  313. X    if (!debug) {
  314. X        append(POSTAMBLE);
  315. X        if (write(1, xlmem, strlen(xlmem)) < 0) {
  316. X            fprintf(stderr, "%s: write failure\n", program);
  317. X            exit(1);
  318. X        }
  319. X    } else 
  320. X        printf("Memory usage: %d bytes, or %d%%\n",
  321. X            memusage, (100*memusage)/MEMSIZ);
  322. X    exit(errflg);
  323. X}
  324.  
  325. X#define    KEY    0
  326. X#define LEVEL    1
  327. X#define    DIR    2
  328. X#define    REPEAT    3
  329. X#define    LFLAG    4
  330. X#define    NUMATTR    5
  331.  
  332. Xdoline(buf)
  333. Xchar    *buf;
  334. X{
  335. X    int        i, nomore, mustbreak;
  336. X    register char    *cp;
  337. X    char        *start;
  338. X    short        new[NUMATTR];
  339. X    static short    old[NUMATTR] = { -2, 0, 0, 0, 0 };
  340.  
  341. X    for (i = 0; i < NUMATTR; i++)
  342. X        new[i] = old[i];
  343. X    cp = buf;
  344. X    while (*cp && isascii(*cp) && !isspace(*cp))
  345. X        cp++;
  346. X    nomore = *cp == 0;
  347. X    *cp++ = 0;
  348. X    if ((new[KEY] = find(buf)) < 0)
  349. X        error("unknown key name '%s'\n", buf);
  350. X    append("|");
  351. X    if (nomore) {
  352. X        if (new[KEY] != old[KEY] + 1)
  353. X            append(itoa(new[KEY]));
  354. X        old[KEY] = new[KEY];
  355. X        append("|");
  356. X        return;
  357. X    }
  358. X    while (*cp && isascii(*cp) && (isspace(*cp) || *cp == ','))
  359. X        cp++;
  360. X    if (!*cp) {
  361. X        if (new[KEY] != old[KEY] + 1)
  362. X            append(itoa(new[KEY]));
  363. X        old[KEY] = new[KEY];
  364. X        append("|");
  365. X        return;
  366. X    }
  367. X    /*
  368. X     * Option parsing
  369. X     *
  370. X     * The options field consists of space-seperated keywords
  371. X     * from the following lists:
  372. X     *
  373. X     *    ctrl, shift, ctrl-shift, meta, 0-31, 64    - shift level
  374. X     *    host, display, graphics            - transmit direction
  375. X     *    never, always                - repeat attribute
  376. X     *    level                    - this is a shift key
  377. X     *    normal                    - everything normal
  378. X     */
  379.  
  380. X    mustbreak = 0;
  381. X    while (!mustbreak && *cp && isascii(*cp) && !isspace(*cp)) {
  382. X        start = cp;        /* assert isascii(*start) */
  383. X        while (*cp && isascii(*cp) && !isspace(*cp) && *cp != ',')
  384. X            cp++;
  385. X        if (*cp == '\t')
  386. X            mustbreak = 1;
  387. X        *cp++ = 0;        /* assert cp > start */
  388. X        switch (*start) {
  389. X        case 'a':
  390. X            new[REPEAT] = 2;
  391. X            break;
  392. X        case 'c':
  393. X            if (index(start, 's'))
  394. X                new[LEVEL] = 3;
  395. X            else
  396. X                new[LEVEL] = 2;
  397. X            break;
  398. X        case 'd':
  399. X            new[DIR] = 2;
  400. X            break;
  401. X        case 'g':
  402. X            new[DIR] = 3;
  403. X            break;
  404. X        case 'h':
  405. X            new[DIR] = 1;
  406. X            break;
  407. X        case 'l':
  408. X            new[LFLAG] = 1;
  409. X            break;
  410. X        case 'm':
  411. X            new[LEVEL] = 64;
  412. X            break;
  413. X        case 'n':
  414. X            if (*(start+1) == 'e')
  415. X                new[REPEAT] = 1;
  416. X            else
  417. X                new[LEVEL] = new[DIR] = new[REPEAT] = new[LFLAG] = 0;
  418. X            break;
  419. X        case 's':
  420. X            new[LEVEL] = 1;
  421. X            break;
  422. X        default:
  423. X            if (isdigit(*start)) {
  424. X                new[LEVEL] = atoi(start);
  425. X                if (new[LEVEL] > 31 && new[LEVEL] != 64)
  426. X                    error("illegal shift level %s\n",
  427. X                               itoa(new[LEVEL]));
  428. X            } else
  429. X                error("unknown option '%s'\n", start);
  430. X        }
  431. X        /* do NOT skip tabs, but DO skip commas */
  432. X        while (*cp && (*cp == ' ' || *cp == '\n' || *cp == ','))
  433. X            cp++;
  434. X    }
  435. X    for (i = 0; i < NUMATTR; i++) {
  436. X        if (i == KEY)
  437. X            continue;
  438. X        if (new[i] != old[i])
  439. X            break;
  440. X    }
  441. X    if (i == NUMATTR) {    /* old attributes are identical to new */
  442. X        if (new[KEY] != old[KEY] + 1)
  443. X            append(itoa(new[KEY]));
  444. X    } else {
  445. X        if (new[KEY] == 200)
  446. X            error("%s string must have normal attributes\n", buf);
  447. X        for (i = 0; i < NUMATTR; i++) {
  448. X            if (new[i] != old[i])
  449. X                append(itoa(new[i]));
  450. X            append(";");
  451. X            old[i] = new[i];
  452. X        }
  453. X        trim(';');
  454. X        memusage++;
  455. X    }
  456. X    append("|");
  457. X    while (*cp && isascii(*cp) && isspace(*cp))
  458. X        cp++;
  459. X    if (!*cp)
  460. X        return;
  461. X    if (new[KEY] == 200) {
  462. X        int    i = memusage;
  463. X        encode(cp);
  464. X        if (memusage - i > MAXPOWERMEM)
  465. X            error("%s string exceeds available memory\n", buf);
  466. X        memusage = i;
  467. X    } else if (new[KEY] == 120 && new[LEVEL] == 3)
  468. X        error("ctrl-shift-reset is not programmable\n", (char *)0);
  469. X    else
  470. X        encode(cp);
  471. X    return;
  472. X}
  473.  
  474.  
  475. Xappend(s)
  476. Xchar    *s;
  477. X{
  478. X    while (*s)
  479. X        *out++ = *s++;
  480. X}
  481.  
  482. Xtrim(c)
  483. Xchar    c;
  484. X{
  485. X    while (*--out == c)
  486. X        ;
  487. X    out++;
  488. X}
  489.  
  490. Xencode(in)
  491. Xchar    *in;
  492. X{
  493. X    int    i;
  494.  
  495. X    while (*in != 0) {
  496. X        if (*in == '\\') {
  497. X            switch (*++in) {
  498. X            case 'n':
  499. X                *in = '\n';
  500. X                break;
  501. X            case 'r':
  502. X                *in = '\r';
  503. X                break;
  504. X            case 'e':
  505. X                *in = '\033';
  506. X                break;
  507. X            case 'b':
  508. X                *in = '\b';
  509. X                break;
  510. X            case 'f':
  511. X                *in = '\f';
  512. X                break;
  513. X            case 'a':
  514. X                *in = '\007';
  515. X                break;
  516. X            case 't':
  517. X                *in = '\t';
  518. X                break;
  519. X            case 's':
  520. X                *in = ' ';
  521. X                break;
  522. X            case '`':
  523. X                /*
  524. X                 * I know I'm gonna regret this...
  525. X                 * \`echo hi`
  526. X                 * is replaced by the result (stdout) of
  527. X                 * executing that command...
  528. X                 */
  529. X                if (rindex(in, '`') && rindex(in, '`') != in) {
  530. X                    char    *cmd, buf[MEMSIZ+1];
  531. X                    FILE    *pfp;
  532.  
  533. X                    cmd = in + 1;
  534. X                    in = rindex(in, '`');
  535. X                    *in++ = 0;
  536. X                    if ((pfp = popen(cmd, "r")) != NULL) {
  537. X                        int    n;
  538.  
  539. X                        n = fread(buf, 1, MEMSIZ, pfp);
  540. X                        if (n > 0) {
  541. X                            buf[n] = 0;
  542. X                            encode(buf);
  543. X                        }
  544. X                        (void) pclose(pfp);
  545. X                    }
  546. X                    continue;
  547. X                } else
  548. X                    *in = '`';
  549. X                break;
  550. X            default:
  551. X                if (!(*in >= '0' && *in <= '7')) {
  552. X                    in--;
  553. X                    break;
  554. X                } else
  555. X                    i = *in++ - '0';
  556. X                if (*in >= '0' && *in <= '7') {
  557. X                    i = 8*i + (*in++ - '0');
  558. X                    if (*in >= '0' && *in <= '7')
  559. X                        i = 8*i + (*in++ - '0');
  560. X                }
  561. X                *--in = (char) i;
  562. X            }
  563. X        }
  564. X        if (*in < ' ') {
  565. X            *out++ = '~';
  566. X            *out++ = (char)((*in & 037)+0100);
  567. X        } else {
  568. X            switch (*in) {
  569. X            case '\177':
  570. X                *out++ = '~';
  571. X                *out++ = '?';
  572. X                break;
  573. X            case '~':
  574. X            case '|':
  575. X                *out++ = '~';
  576. X                *out++ = *in;
  577. X                break;
  578. X            default:
  579. X                *out++ = *in;
  580. X            }
  581. X        }
  582. X        memusage++;
  583. X        in++;
  584. X    }
  585. X}
  586.  
  587. X/*
  588. X * The following table gives correspondence between key name and number.
  589. X * Names are seperated by space, and each string represents 20 keys in
  590. X * increasing number order.
  591. X */
  592.  
  593. Xchar    *lookup[] =
  594. X{ "s1 s2 space s3 s4 s5 s6",
  595. X  "pause shift-l z x c v b n m , . / shift-r scroll zoom",
  596. X  "_ ctrl a s d f g h j k l ; ' return back-space",
  597. X  "tab q w e r t y u i o p [ ] line-feed del",
  598. X  "esc 1 2 3 4 5 6 7 8 9 0 - = ` \\ break",
  599. X  "0P _ 00P .P enter ,P 1P 2P 3P _ tabP 4P 5P 6P +P _ 7P 8P 9P -P",
  600. X  "reset setup f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17 f18",
  601. X  "send erase edit delete insert print _ _ _ _ Header Trailer ENQ DA",
  602. X  "_",
  603. X  "_",
  604. X  "Power-on",
  605. X  0
  606. X};
  607.  
  608. X/*
  609. X * This little baby relies on contiguous allocation of the strings in
  610. X * the lookup[] array. If your compiler doesn't grok that, it's simplicity
  611. X * itself to wrap a loop around the body of this thing.
  612. X */
  613.  
  614. Xint
  615. Xfind(keyname)
  616. Xchar    *keyname;
  617. X{
  618. X    register char    *cp, *s;
  619. X    int    key;
  620.  
  621. X    key = 0;
  622. X    for (cp = lookup[0]; *cp; cp++) {
  623. X        s = keyname;
  624. X        while (*s && *cp == *s)
  625. X            cp++, s++;
  626. X        if (*s == 0 && (*cp == ' ' || *cp == 0))
  627. X            return key;
  628. X        while (*cp && *cp != ' ')
  629. X            cp++;
  630. X        if (!*cp)
  631. X            key = 20*((key/20)+1);
  632. X        else
  633. X            key++;
  634. X    }
  635. X    return -1;
  636. X}
  637.  
  638. Xchar *
  639. Xitoa(num)
  640. Xint    num;
  641. X{
  642. X    static char    digs[10];
  643. X    char        *cp;
  644.  
  645. X    cp = digs + 9;
  646. X    *cp-- = '\0';
  647. X    if (num == 0) {
  648. X        *cp = '0';
  649. X        return cp;
  650. X    }
  651. X    while (num > 0) {
  652. X        *cp-- = (num % 10) + '0';
  653. X        num /= 10;
  654. X    }
  655. X    return cp+1;
  656. X}
  657.  
  658. Xerror(format, string)
  659. Xchar    *format, *string;
  660. X{
  661. X    fprintf(stderr, "%s: file %s line %d: ", program, file, lineno);
  662. X    fprintf(stderr, format, string);
  663. X    exit(1);
  664. X}
  665. @//E*O*F aaxl.c//
  666. chmod u=rw,g=rw,o=rw $OUT
  667.  
  668. echo x - aaxl.l
  669. if test -f aaxl.l ; then
  670.     echo aaxl.l exists, putting output in $$aaxl.l
  671.     OUT=$$aaxl.l
  672.     STATUS=1
  673. else
  674.     OUT=aaxl.l
  675. fi
  676. sed 's/^X//' > $OUT <<'@//E*O*F aaxl.l//'
  677. X.TH AAXL l "University of Toronto"
  678. X.SH NAME
  679. Xaaxl - program Ann Arbor XL keyboard
  680. X.SH SYNOPSIS
  681. X.B aaxl
  682. X[
  683. X.B \-a
  684. X] [
  685. X.B \-d
  686. X] [
  687. X.B \-l
  688. X] [
  689. X.B \-v
  690. X] [
  691. X.I file
  692. X\&... ]
  693. X.SH DESCRIPTION
  694. X.PP
  695. XAaxl reads a description of keynames and corresponding attributes and a text
  696. Xto program the key with. Several files may be given as arguments. With no files
  697. Xspecified, $HOME/.aaxlrc is read. A filename of \fB-\fR reads from stdin.
  698. X.PP
  699. XThe \fB-a\fR flag is used to append the downloaded strings to the current
  700. Xstate. If not given, programmable strings are cleared before defining any
  701. Xnew string.
  702. X.PP
  703. XThe \fB-d\fR flag is a debug flag, causing Ann Arbor XL memory usage statistics
  704. Xto be printed instead of loading the programmable strings. An absolute
  705. Xbytecount, and the percentage of programmable strings memory that would be
  706. Xused, is printed.
  707. X.PP
  708. XThe \fB-l\fR flag asks for the key programming lock to be set, after the
  709. Xprogrammable strings have been loaded.
  710. X.PP
  711. XThe \fB-v\fR flag asks the program to be verbose and print the body of the
  712. Xcontrol string it would send to the Ann Arbor, to stdout. The entire control
  713. Xstring is still written out, unless \fB-d\fR is used.
  714. X.PP
  715. XThe program collects definitions of programmable keys from the files it reads.
  716. XThe definitions are wrapped in preamble and postamble control sequences, and
  717. Xsend to stdout. Other simultaneous output to the terminal will probably corrupt
  718. Xthe programming command, though it is written using a single (hopefully atomic)
  719. Xoutput operation.
  720. X.PP
  721. XAs a side benefit, to initialize the programmable strings on the XL, use
  722. X.sp
  723. X.nf
  724. X    aaxl /dev/null
  725. X.fi
  726. X.PP
  727. XEach input contains lines specifying a key to upload a programmable
  728. Xstring for. Lines starting with #, and empty lines, are ignored.
  729. XThe format of each line is
  730. X.sp
  731. X.nf
  732. X    name <whitespace> options [ <whitespace> <tab> text ]
  733. X.fi
  734. X.sp
  735. Xwhere <whitespace> is blanks, tabs, and commas. The text is optional,
  736. Xif not there the key will revert to default programmed text (usually none).
  737. XThis can be used to change other behavior of a key.
  738. X.PP
  739. XThe options field consists of keywords from the following lists:
  740. X.sp
  741. X.nf
  742. Xctrl, shift, ctrl-shift, meta, 0-31, 64    - shift level
  743. Xhost, display, graphics                - transmit direction
  744. Xnever, always                        - repeat attribute
  745. Xlevel                            - this is a shift key
  746. Xnormal                            - everything normal
  747. X.fi
  748. X.PP
  749. XThe defaults for all but the 'normal' keyword are whatever the previous
  750. Xoption value was for the previous key. The normal (and initial default)
  751. Xvalues correspond to all-zero parameters. See the XL manual for detailed
  752. Xexplanation of the options.
  753. X.PP
  754. XThe text field follows one or more blanks or tabs after the option field
  755. Xand consists of everything from there till a newline. The string may contain
  756. Xall the usual C string escapes (\\###, \\n\\t\\s\\a\\b\\f\\r\\e), and in
  757. Xaddition may contain one sequence like \\`...` where ... is a command to be
  758. Xexecuted by the shell. The result (stdout) of the command is interpolated in
  759. Xplace of the \\` escape.
  760. X.PP
  761. XKey names used in the first field correspond to the legend on the caps. Keys
  762. Xin the keypad group have a capital P appended to the cap name. The following
  763. Xlist shows the complete list of recognized names. Note that key names which
  764. Xstart with a capital letter do not correspond to a keyboard key, but rahter
  765. Xto other capabilities of the XL. For example, DA programs the answerback
  766. Xstring (Device Attributes), Power-on the power-on string, etc.
  767. X.sp
  768. Xs1 s2 space s3 s4 s5 s6
  769. Xpause shift-l z x c v b n m , . / shift-r scroll zoom
  770. Xctrl a s d f g h j k l ; ' return back-space
  771. Xtab q w e r t y u i o p [ ] line-feed del
  772. Xesc 1 2 3 4 5 6 7 8 9 0 - = ` \\ break
  773. X0P 00P .P enter ,P 1P 2P 3P tabP 4P 5P 6P +P 7P 8P 9P -P
  774. Xreset setup f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17 f18
  775. Xsend erase edit delete insert print Header Trailer ENQ DA
  776. XPower-on
  777. X.PP
  778. XThis program reports errors, including XL memory overflow that could
  779. Xoccur. All errors are fatal. The program doesn't send an upload string
  780. Xto the terminal unless no errors were detected at all. Memory allocation
  781. Xfor the upload string is done dynamically in the program, so excessively
  782. Xlarge string sequences are handled. Space-optimal output is produced.
  783. X.SH ENVIRONMENT
  784. X.PP
  785. XWhen no file arguments are given to the program, the value of the
  786. X.I HOME
  787. Xenvironment variable is assumed to be a directory containing a .aaxlrc file,
  788. Xwhich will be read if it exists.
  789. X.SH SEE ALSO
  790. X"XL Series User Guide" by Ann Arbor Terminals, Inc.
  791. X.SH AUTHOR
  792. XRayan Zachariassen, University of Toronto CSRI/AI.
  793. X.SH BUGS
  794. XIf a command is embedded in the key text, the last backquote in the text
  795. Xmust correspond to the end of the command escape.
  796. X.PP
  797. XProbably doesn't handle NUL's in strings terribly gracefully. Who does.
  798. @//E*O*F aaxl.l//
  799. chmod u=rw,g=rw,o=rw $OUT
  800.  
  801. echo Inspecting for damage in transit...
  802. temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
  803. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  804. cat > $temp <<\!!!
  805.       20     170    1002 README
  806.       11      33     229 Makefile
  807.      579    2171   12997 aaxl.c
  808.      121     851    4723 aaxl.l
  809.      731    3225   18951 total
  810. !!!
  811. wc  README Makefile aaxl.c aaxl.l | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  812. if test -s $dtemp ; then
  813.     echo "Ouch [diff of wc output]:"
  814.     cat $dtemp
  815.     STATUS=1
  816. elif test $STATUS = 0 ; then
  817.     echo "No problems found."
  818. else
  819.     echo "WARNING -- PROBLEMS WERE FOUND..."
  820. fi
  821. exit $STATUS
  822.